use std::{collections::HashMap, sync::Arc};

use monitor::{CompleterSuggestion, Monitor, MonitorCommand};

use super::fdinfo::{fdinfo_get, mon_fd_completer};
use crate::{DfsError, DfsResult};

struct WriteCommand;

impl WriteCommand {
    fn do_write(&self, args: &HashMap<String, String>) -> DfsResult<()> {
        let fd = args.get("fd").unwrap().parse::<u64>().map_err(|_| DfsError::InvalidArgs)?;
        let file = fdinfo_get(fd)?;
        let buf = args.get("data").unwrap();
        file.write(buf)?;
        Ok(())
    }
}

impl MonitorCommand for WriteCommand {
    fn mon_protocol_exec(&self, args: &monitor::Protocol) -> DfsResult<monitor::Protocol> {
        self.do_write(args)?;
        let hash = HashMap::new();
        Ok(hash)
    }

    fn mon_readline_arg_type(&self) -> Option<&'static str> {
        Some("fd:u64,data:*")
    }
    fn mon_readline_completer(&self, args: &[&str], is_space: bool) -> Option<CompleterSuggestion> {
        mon_fd_completer(args, is_space)
    }

    fn mon_readline_exec(
        &self,
        args: &HashMap<String, String>,
        _: &monitor::MonitorPrinter,
    ) -> DfsResult<()> {
        self.do_write(args)
    }

    fn mon_readline_help(&self) -> String {
        String::from("向 fd 写入数据")
    }

    fn mon_readline_long_help(&self) -> Option<String> {
        Some(String::from("write <fd> <data>"))
    }
}

pub(crate) fn monitor_command_write_register(mon: &Monitor) {
    mon.register_command("write", Arc::new(WriteCommand)).unwrap();
}
